﻿//-----------------------------------------------------------------------
// <copyright file="OfficeColorPicker.cs" company="LMT">
//     Copyright (c) by La Minh Thuận.
// </copyright>
// <author>thuanla1985@hotmail.com</author>
//-----------------------------------------------------------------------
namespace LMT.Forms
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;

    /// <summary>
    /// The drop down color combo box with office style
    /// </summary>
    public partial class OfficeColorPicker : ComboBox
    {
        /// <summary>
        /// WM USER value
        /// </summary>
        private const int WmUser = 0x0400;

        /// <summary>
        /// WM REFLECT value
        /// </summary>
        private const int WmReflect = WmUser + 0x1C00;

        /// <summary>
        /// WM COMMAND value
        /// </summary>
        private const int WmCommand = 0x0111;

        /// <summary>
        /// CBN DROPDOWN value
        /// </summary>
        private const int CbnDropDown = 7;

        /// <summary>
        /// instance of OfficeMenuHelper
        /// </summary>
        private OfficeMenuHelper colorPlate;

        /// <summary>
        /// Initializes a new instance of the <see cref="OfficeColorPicker"/> class.
        /// </summary>
        public OfficeColorPicker()
        {
            this.InitializeComponent();
            this.OnInit();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="OfficeColorPicker"/> class.
        /// </summary>
        /// <param name="container">The container.</param>
        public OfficeColorPicker(IContainer container)
        {
            container.Add(this);
            this.InitializeComponent();
            this.OnInit();
        }

        /// <summary>
        /// Occurs when [selected color changed].
        /// </summary>
        [Browsable(true)]
        public event EventHandler SelectedColorChanged;

        /// <summary>
        /// Gets or sets the color.
        /// </summary>
        /// <value>The color.</value>
        [Browsable(true)]
        public Color Color
        {
            get { return this.colorPlate.ColorPalette.SelectedColor; }
            set { this.colorPlate.ColorPalette.SelectedColor = value; }
        }

        /// <summary>
        /// HIs the word.
        /// </summary>
        /// <param name="n">The low word integer value.</param>
        /// <returns>integer value</returns>
        public static int HIWord(int integer)
        {
            return (integer >> 16) & 0xffff;
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ComboBox.OnBindingContextChanged"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnBindingContextChanged(EventArgs e)
        {
            base.OnBindingContextChanged(e);

            if (this.Items.Count != 1)
            {
                this.Items.Clear();
                this.Items.Add("Color");
                this.SelectedIndex = 0;
            }
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.ComboBox.DrawItem"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.DrawItemEventArgs"/> that contains the event data.</param>
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            if (e.Index > -1)
            {
                // Paints the rectangle by the current color.
                e.Graphics.FillRectangle(new SolidBrush(this.Color), e.Bounds);
                Rectangle rec = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1);

                if ((e.State & DrawItemState.Focus) == 0)
                {
                    // Draw the border rectangle
                    using (Pen pen = new Pen(Color.LightGray))
                    {
                        e.Graphics.DrawRectangle(pen, rec);
                    }
                }
                else
                {
                    // Draw the border rectangle
                    using (Pen borderPen = new Pen(Color.LightGray, 1))
                    {
                        e.Graphics.DrawRectangle(borderPen, rec);
                    }

                    // Draw the focus rectangle
                    Pen focusPen = new Pen(Color.Gray, 1);
                    focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
                    e.Graphics.DrawRectangle(focusPen, rec);
                    focusPen.Dispose();
                }
            }
        }

        /// <summary>
        /// Processes Windows messages.
        /// </summary>
        /// <param name="m">The Windows <see cref="T:System.Windows.Forms.Message"/> to process.</param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == (WmReflect + WmCommand))
            {
                if (HIWord((int)m.WParam) == CbnDropDown)
                {
                    this.ShowDropDown();
                    return;
                }
            }

            base.WndProc(ref m);
        }

        /// <summary>
        /// Called when [init].
        /// </summary>
        private void OnInit()
        {
            SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer, true);

            this.Items.Add("Color");
            this.SelectedIndex = 0;
            this.DropDownHeight = 1;

            this.DrawMode = DrawMode.OwnerDrawFixed;
            this.DropDownStyle = ComboBoxStyle.DropDownList;

            this.colorPlate = new OfficeMenuHelper();
            this.colorPlate.ColorPalette.SelectedColorChanged += new EventHandler(this.ColorPlateSelectedColorChanged);
        }

        /// <summary>
        /// Handles the SelectedColorChanged event of the colorPlate control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void ColorPlateSelectedColorChanged(object sender, EventArgs e)
        {
            if (this.SelectedColorChanged != null)
            {
                this.SelectedColorChanged(this, new EventArgs());
            }
        }

        /// <summary>
        /// Shows the drop down.
        /// </summary>
        private void ShowDropDown()
        {
            if (this.colorPlate != null)
            {
                this.colorPlate.Show(this, new Point(0, this.Height));
            }
        }
    }
}